#ifndef __WIZ_DATATYPE_ANY_HPP__SHANHAOBO_19800429__
#define __WIZ_DATATYPE_ANY_HPP__SHANHAOBO_19800429__

#include <algorithm>
#include <typeinfo>

#include "../Base/WizBase.hpp"

namespace Wiz
{
    namespace DataType
    {
        namespace Any
        {
            struct ICore
            {
                virtual ~ICore(){}
                virtual const ::std::type_info& Type() const    = 0;
                virtual ICore* Clone() const                    = 0;
            };

            template<typename T>
            struct Core : public ::Wiz::DataType::Any::ICore
            {
                T m_Core;
                Core(const T& value) : m_Core(value){}
                virtual const ::std::type_info& Type() const
                {
                    return typeid(T);
                }
                virtual ::Wiz::DataType::Any::ICore* Clone() const
                {
                    return new Core(this->m_Core);
                }
            };

            class Type
            {
                ::Wiz::DataType::Any::ICore* m_Content;
            public:
                Type() : m_Content(WIZ_NULLPTR){}
                ~Type()
                {
                    delete m_Content;
                }
                template<typename T>
                Type(const T& value): m_Content(new ::Wiz::DataType::Any::Core<T>(value))
                {}
                Type(const Type& other) : m_Content(::Wiz::IsValidPtr(other.m_Content) ? other.m_Content->Clone() : 0)
                {}
            public:
                Type& Swap(Type& rhs)
                {
                    ::Wiz::Swap(m_Content, rhs.m_Content);
                    return *this;
                }
                //assign from a value of any Type
                template<typename T>
                Type& operator=(const T& rhs)
                {
                    Type(rhs).Swap(*this);
                    return *this;
                }
                //assign from another any object
                Type& operator=(const Type& rhs)
                {
                    Type(rhs).Swap(*this);
                    return *this;
                }
                ::Wiz::Bool::Type IsEmpty() const 
                {
                    return !(this->m_Content);
                }
                const ::std::type_info& GetType() const
                {
                    if (::Wiz::NotValidPtr(this->m_Content))
                    {
                        return typeid(::Wiz::Void::Type);
                    }
                    return this->m_Content->Type();
                }

                template<typename RType> RType& Get()
                {
                    WIZ_ASSERT(this->GetType() == typeid(RType));
                    return (reinterpret_cast<::Wiz::DataType::Any::Core<RType>*>(this->m_Content)->m_Core);
                }
            }; /// end of class Type
        } /// end of namespace Any
    } /// end of namespace DataType

    namespace Any
    {
        WIZ_DECLARE(::Wiz::DataType::Any::Type);
    } /// end of namespace Any
} /// end of namespace Wiz

#endif /*__WIZ_DATATYPE_ANY_HPP__SHANHAOBO_19800429__*/
